//
//  CPWaveView.m
//  WaveViewTest
//
//  Created by MorpLCP on 2017/6/15.
//  Copyright © 2017年 yizhan. All rights reserved.
//

#import "CPWaveView.h"

static CGFloat CPMaxVariable = 1.6; // 最大增量
static CGFloat CPMinVariable = 1.0; // 最小增量
static CGFloat CPMinStepLength = 0.01; // 单步移动的距离

@interface CPWaveView()
{
    CGFloat _amplitude; // 振幅
    CGFloat _cycle; // 移动周期
    CGFloat _speed; // 移动速度
    CGFloat _offsetX; // X偏移量
    CGFloat _offsetY; // Y偏移量
    CGFloat _variable; // 增量
    CGFloat _height; // 高度
    BOOL _increase; // 是否需要增加
}

@property (nonatomic, strong) CADisplayLink *displaylink; // 计时器
@property (nonatomic, strong) CAShapeLayer  *firstWaveLayer; // 顶部波浪层
@property (nonatomic, strong) CAShapeLayer  *secondWaveLayer; // 底部波浪层
@property (nonatomic) NSUInteger times;

@end

@implementation CPWaveView

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame])
    {
        [self setup];
        return self;
    }
    return nil;
}

- (void)setup
{
    self.backgroundColor = [UIColor clearColor];
    _displaylink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkTric:)];
    _displaylink.frameInterval = 2;
    [_displaylink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
    _displaylink.paused = YES;
    
    _firstWaveLayer = [CAShapeLayer layer];
    _firstWaveLayer.fillColor = [UIColor lightGrayColor].CGColor;
    
    _secondWaveLayer = [CAShapeLayer layer];
    _secondWaveLayer.fillColor = [UIColor whiteColor].CGColor;
    
    _topWaveColor = [UIColor lightGrayColor];
    _bottomWaveColor = [UIColor whiteColor];
    _times = 2;
    _cycle = 2 * M_PI / self.frame.size.width;
    [self setupProperty];
}

- (void)setTopWaveColor:(UIColor *)topWaveColor
{
    _topWaveColor = topWaveColor;
    _firstWaveLayer.fillColor = topWaveColor.CGColor;
}

- (void)setBottomWaveColor:(UIColor *)bottomWaveColor
{
    _bottomWaveColor = bottomWaveColor;
    _secondWaveLayer.fillColor = bottomWaveColor.CGColor;
}

- (void)setWaveHeight:(CGFloat)waveHeight
{
    _waveHeight = waveHeight;
    _times = waveHeight / 10 + 1;
}

- (void)setWaveSpeed:(CGFloat)waveSpeed
{
    _waveSpeed = waveSpeed;
    _speed = waveSpeed / M_PI;
}

- (void)setupProperty
{
    _amplitude = CPMaxVariable;
    _variable = CPMaxVariable;
    _increase = NO;
}

- (CGFloat)currentHeight
{
    return MAX(2 * _height, 0);
}

- (void)displayLinkTric:(CADisplayLink *)displayLink
{
    [self configWaveAmplitude];
    [self configWaveOffset];
    [self configFirstWaveLayerPath];
    [self configSecondWaveLayerPath];
}

- (void)configWaveAmplitude
{
    if (_increase)
    {
        _variable += CPMinStepLength;
    }
    else
    {
        CGFloat minus = CPMinStepLength;
        _variable -= minus;
        if (_variable <= 0.00)
        {
            [self stop];
        }
    }
    
    if (_variable <= CPMinVariable)
    {
        _increase = YES;
    }
    
    if (_variable >= CPMaxVariable)
    {
        _increase = NO;
    }
    
    if (_times >= 7)
    {
        _times = 7;
    }
    _amplitude = _variable * _times;
    _height = CPMaxVariable * _times;
}

- (void)configWaveOffset
{
    _offsetX += _speed;
    _offsetY =  [self currentHeight] - _amplitude;
}

- (void)configFirstWaveLayerPath
{
    CGMutablePathRef path = CGPathCreateMutable();
    CGFloat y = _offsetY;
    CGPathMoveToPoint(path, nil, 0, y);
    CGFloat waveWidth = self.frame.size.width;
    for (float x = 0.0f; x <= waveWidth; x++)
    {
        y = _amplitude * sin(_cycle * x + _offsetX) + _offsetY;
        CGPathAddLineToPoint(path, nil, x, y);
    }
    CGPathAddLineToPoint(path, nil, waveWidth, self.frame.size.height);
    CGPathAddLineToPoint(path, nil, 0, self.frame.size.height);
    CGPathCloseSubpath(path);
    _firstWaveLayer.path = path;
    CGPathRelease(path);
}

- (void)configSecondWaveLayerPath
{
    CGMutablePathRef path = CGPathCreateMutable();
    CGFloat y = _offsetY;
    CGPathMoveToPoint(path, nil, 0, y);
    CGFloat forawrd = M_PI / _cycle / 2;
    CGFloat waveWidth = self.frame.size.width;
    for (float x = 0.0f; x <=  waveWidth ; x++)
    {
        y = _amplitude * cos(_cycle * x + _offsetX - forawrd) + _offsetY;
        CGPathAddLineToPoint(path, nil, x, y);
    }
    CGPathAddLineToPoint(path, nil, waveWidth, self.frame.size.height);
    CGPathAddLineToPoint(path, nil, 0, self.frame.size.height);
    CGPathCloseSubpath(path);
    _secondWaveLayer.path = path;
    CGPathRelease(path);
}

- (void)start
{
    if (self.displaylink.paused == NO)
    {
        self.firstWaveLayer.path = nil;
        self.secondWaveLayer.path = nil;
        [self.firstWaveLayer removeFromSuperlayer];
        [self.secondWaveLayer removeFromSuperlayer];
    }
    [self setupProperty];
    [self.layer addSublayer:self.firstWaveLayer];
    [self.layer addSublayer:self.secondWaveLayer];
    self.displaylink.paused = NO;
}

- (void)stop
{
    self.displaylink.paused = YES;
    self.firstWaveLayer.path = nil;
    self.secondWaveLayer.path = nil;
    [self.firstWaveLayer removeFromSuperlayer];
    [self.secondWaveLayer removeFromSuperlayer];
}

- (void)invalidate
{
    [self.displaylink invalidate];
}

@end
